package com.artoxian.application;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.artoxian.exception.GarminConnectorException;
import com.artoxian.exception.PropertyNotFoundException;

public class Application {
	private static Logger log = Logger.getLogger(Application.class);
	
	private static Application instance;
	
	private final String PROPERTIES_FILE_LOCATION = "application.properties";
	
	private GarminConnector garminConnector;

	// Properties
	private Properties properties;
	private String username;
	private String password;
	private String directory;
	private String logLevel;
	
	private List<String> existingActivityIds;
	private List<File> pendingFiles;
	
	public static void main(String[] args) {
		
		// Call the singleton
		Application application = Application.getInstance();
		
		// First load properties from disk
		try {
			application.loadProperties();
		} catch (IOException exception) {
			// Exit if properties file not found
			log.error("Properties file does not exist at: " + application.PROPERTIES_FILE_LOCATION, exception);
			System.exit(1);
		} catch (PropertyNotFoundException exception) {
			// Exit if properties file not found
			log.error(exception.getMessage(), exception);
			System.exit(1);
		}
		
		// Set the log level
		application.setLogLevel();
		
		// Login to garmin
		application.connectToGarmin();
		
		// Lookup the existing user's activities
		application.lookupActivities();
		
		// Search the directory for files pending
		application.setPendingFiles();
		
		// Process the files
		application.processPendingFiles();
    }
	
	public static Application getInstance() {
		if (instance == null) {
			instance = new Application();
		}
		
		return instance;
	}
	
	private void loadProperties() throws IOException, PropertyNotFoundException {
		// Initialise the properties
		properties = new Properties();
		File propertiesFile = new File(PROPERTIES_FILE_LOCATION);
		
		// Attempt to load the application properties
		properties.load(new FileInputStream(propertiesFile));
		
		// Set the internal variables from properties file
		username = getProperty("username");
		password = getProperty("password");
		directory = getProperty("directory");
		logLevel = getProperty("logLevel");
	}
	
	private String getProperty(String key) throws PropertyNotFoundException {
		// Attempt to get the property
		String property = properties.getProperty(key);
		
		// Throw exception if it is null
		if (property == null) {
			throw new PropertyNotFoundException("Property \"" + key + "\" not found in" + PROPERTIES_FILE_LOCATION);
		} else {
			return property;
		}
	}
	
	private void setLogLevel() {
		// Set log level
		if ("debug".equals(logLevel)) {
			LogManager.getRootLogger().setLevel(Level.DEBUG);
		}
		else {
			LogManager.getRootLogger().setLevel(Level.INFO);
		}
	}
	
	private void connectToGarmin() throws IOException {
		// Login to garmin
		garminConnector = new GarminConnector();
		garminConnector.login(username, password);
	}
	
	private void lookupActivities() throws IOException, GarminConnectorException {
		existingActivityIds = garminConnector.setExistingActivityIds();
	}
	
	private void setPendingFiles() throws IOException, FileNotFoundException {
		pendingFiles = new ArrayList<File>();
		FileProcessor fileProcessor = new FileProcessor(existingActivityIds);
		fileProcessor.processDirectory(new File(directory));
	}
	
	private void processPendingFiles() throws IOException, GarminConnectorException {						
		// Loop through the pendingFiles
		for (File file : pendingFiles) {
			garminConnector.upload(file);
		}
	}
	
	public void addPendingFile(File file) {
		pendingFiles.add(file);
	}
	
	/*
	public void monitorFolder() throws Exception {
		// Initialise the monitoring of the folder
		final FolderMonitor folderMonitor = new FolderMonitor(new File(GarminProperties.getInstance().getDirectory()));
		folderMonitor.start();
 
		// Make sure the monitoring is ended when the app shuts down
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("Stopping monitor.");
                    folderMonitor.stop();
                } catch (Exception ignored) {
                }
            }
        }));
        
        // Run forever
        while(true) {
        	
        }
	}*/
}
